昨天完成表格後,今天來寫前端顯示未來鄉鎮溫度折線圖和降雨機率長條圖,js 有很多畫圖表的套件,我這邊選Chart.js,Chart.js一個開源的套件,裡面有許多常見的圖表,長條圖、折線圖、圓餅圖等等,官網文件也滿清楚的。
一樣先寫Api,這裡就用同一個getPdfWeather(),多回傳一個chartTemperatureDict ,圖表格式,這裡也先把chart js 的資料處理好,前端js就直接撈就好。
ex
[{
locationName: "文山區"
tableDataList: ...,
chartTemperatureDict: {
temperatureList: [24, 24, 26, 26, 24],
aTemperatureList: [24, 24, 26, 26, 24],
pop6HList: [20, 40, 20, 40],
}
},
locationName: "松山區"
tableDataList: ...,
chartTemperatureDict: {
temperatureList: [24, 24, 26, 26, 24],
aTemperatureList: [24, 24, 26, 26, 24],
pop6HList: [20, 40, 20, 40],
}
},
]
main/views.py 局部程式碼
def convertChart(dataDict):
todayDate = datetime.datetime.today().date()
tomorrow = todayDate + datetime.timedelta(days=1)
tomorrowText = tomorrow.strftime('%Y-%m-%d')
showDateText = tomorrowText
temperatureList = []
for temperatureDict in dataDict["temperatureDictList"]:
dataTime = temperatureDict["dataTime"]
if showDateText in dataTime:
temperatureList.append(temperatureDict['value'])
aTemperatureList = [] # 省略
pop6HList = []
for pop6HDict in dataDict["pop6HDictList"]:
startTime = pop6HDict["startTime"]
if showDateText in startTime:
pop6HList.append(pop6HDict['value'])
pop6HList.append(pop6HDict['value'])
return {
"temperatureList": temperatureList,
"aTemperatureList": aTemperatureList,
"pop6HList": pop6HList,
}
def getPdfWeather(request):
...
for dataDict in dataDictList:
resultList.append({
"locationName": dataDict["locationName"],
"tableDataList": convertToList(dataDict),
"chartTemperatureDict": convertChart(dataDict)
})
return JsonResponse(resultList, safe=False)
main/main.html 局部程式碼,只列新增的
// render 折線圖的canvas,要設定不一樣的id
const renderLineChart = (dataObj) => {
return `<canvas id="lineChart_${dataObj.locationName}" width="400" height="100"></canvas>`
}
// render 長條圖的canvas,要設定不一樣的id
const renderBarChart = (dataObj) => {
return `<canvas id="barChart_${dataObj.locationName}" width="400" height="100"></canvas>`
}
const renderWeatherCard = (dataObj) => {
return `
<div class="card">
<div class="card-header">
${dataObj.locationName}
</div>
<div class="card-body">
${renderTable(dataObj)}
${renderLineChart(dataObj)} // 多call
${renderBarChart(dataObj)} // 多call
</div>
</div>
`
}
// 產生折線圖物件
const renderLineChartInit = (dataObj) => {
let canvas = document.getElementById(`lineChart_${dataObj.locationName}`);
let ctx = canvas.getContext('2d');
let myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00"],
datasets: [{
label: '溫度',
backgroundColor: 'green',
borderColor: 'green',
data: dataObj.chartTemperatureDict.temperatureList,
fill: false,
}, {
label: '體感溫度',
fill: false,
backgroundColor: 'blue',
borderColor: 'blue',
data: dataObj.chartTemperatureDict.aTemperatureList,
}]
},
options: {
responsive: true,
title: {
display: true,
text: '未來鄉鎮溫度折線圖'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: '時間'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: '溫度'
}
}]
}
}
})
}
// 產生長條圖物件
const renderBarChartInit = (dataObj) => {
let canvas = document.getElementById(`barChart_${dataObj.locationName}`);
let ctx = canvas.getContext('2d');
let myLineChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00"],
datasets: [{
label: '降雨機率',
backgroundColor: 'lightblue',
borderColor: 'black',
borderWidth: 1,
data: dataObj.chartTemperatureDict.pop6HList,
},]
},
options: {
responsive: true,
title: {
display: true,
text: '未來鄉鎮降雨機率長條圖'
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: '時間'
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
min: 0,
max: 100,
steps: 10,
},
display: true,
scaleLabel: {
display: true,
labelString: '降雨機率%'
}
}]
}
}
})
}
const reqGetPdfWeather = (selectedDistrictChxArr) => {
...
$.ajax({
url: `/api/getPdfWeather/?${queryString}`,
processData: false,
contentType: false,
success: (res) => {
res.map((dataObj) => {
$("#weatherDiv").append(renderWeatherCard(dataObj))
// 先有canvas,再寫chart
renderLineChartInit(dataObj)
renderBarChartInit(dataObj)
})
}
})
}
結果圖 把圖表放在表格下方
結語
js 有點太長了,要重構寫到js檔案了
參考資料: